/*
 *------------------------------------------------------------------------------
 * @File      :    a6208.c
 * @Date      :    2021-3-20
 * @Author    :    lomboswer <lomboswer@lombotech.com>
 * @Brief     :    Source file for MDP(Media Development Platform).
 *
 * Copyright (C) 2020-2021, LomboTech Co.Ltd. All rights reserved.
 *------------------------------------------------------------------------------
 */
#include "ei_comm_camera.h"

#include "extdrv_usr.h"
#include "ei_comm_extdev.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#define DEV_ID 6208
#define DEV_NAME  "a6208"

static EXT_DEV_STATE_S gastExtDev[VISS_MAX_DEV_NUM] = {0};
static EI_BOOL g_sbIrInit = EI_FALSE;
typedef struct eiIR_S {
    pthread_mutex_t mutex;
} IR_S;

static CAMERA_POWER_ACT_S s_astCloseAct[] = {
    {SNS_IR_RESET, SNS_UP},
    {SNS_IR_PWDN, SNS_DOWN},
    {SNS_DELAY, 50},
    {SNS_IR_RESET, SNS_DOWN},
};
static CAMERA_POWER_ACT_S s_astOpenAct[] = {
    {SNS_IR_RESET, SNS_DOWN},
    {SNS_IR_PWDN, SNS_UP},
    {SNS_DELAY, 50},
    {SNS_IR_PWDN, SNS_DOWN},
};

void EXTDEV_Exit(VISS_DEV dev)
{
    extprintf("--%s Exit--\n", DEV_NAME);
}

EI_S32 EXTDEV_SetAttr(VISS_DEV dev,const CTL_ATTR_S *stCtlAttr)
{
    EI_S32 s32Ret = EI_SUCCESS;
    CAMERA_POWER_ACT_S *pstUpAct;
    EI_U32 u32Cnt = 0;
    IR_STATE_E eState = stCtlAttr->unAttr.stIrCut.eState;
    IR_S *pIr = EI_NULL;

    EXT_DEV_STATE_S *pastExtDevCtx = EI_NULL;

    EXT_DEV_GET_CTX(dev, pastExtDevCtx);
    CAMERA_CHECK_POINTER(pastExtDevCtx);

    pIr = (IR_S *)pastExtDevCtx->pvPriv;

    if (stCtlAttr->enType != IR_CUT) {
        PRT_VISS_ERR("%s  type err\n", DEV_NAME);
        return EI_FAILURE;
    }

    pstUpAct = eState ? s_astCloseAct : s_astOpenAct;
    u32Cnt = eState ? ARRARSIZE(s_astCloseAct) : ARRARSIZE(s_astOpenAct);

    pthread_mutex_lock(&pIr->mutex);
    pastExtDevCtx->eIr = eState;
    s32Ret = VISS_SetPinState(dev, pstUpAct, u32Cnt);
    pthread_mutex_unlock(&pIr->mutex);

    CAMERA_CHECK_SUCCESS(s32Ret);

    return s32Ret;
}


EI_S32 EXTDEV_GetAttr(VISS_DEV dev, CTL_ATTR_S *pstCtlAttr)
{
    EI_S32 s32Ret = EI_SUCCESS;
    EXT_DEV_STATE_S *pastExtDevCtx = EI_NULL;
    IR_S *pIr = EI_NULL;

    EXT_DEV_GET_CTX(dev, pastExtDevCtx);
    CAMERA_CHECK_POINTER(pastExtDevCtx);

    pIr = (IR_S *)pastExtDevCtx->pvPriv;

    pthread_mutex_lock(&pIr->mutex);

    switch (pstCtlAttr->enType) {
        case IR_CUT:
            pstCtlAttr->unAttr.stIrCut.eState = pastExtDevCtx->eIr;
            break;
        default:
            PRT_VISS_ERR("%s  type err\n", DEV_NAME);
            s32Ret =  EI_FAILURE;
    }
    pthread_mutex_unlock(&pIr->mutex);

    return s32Ret;
}

EI_S32 EXTDEV_Init(VISS_DEV dev)
{
    EI_S32 s32Ret = EI_SUCCESS;
    EXT_DEV_STATE_S *pastExtDevCtx = EI_NULL;
    CTL_ATTR_S stCtlAttr;

    EXT_DEV_GET_CTX(dev, pastExtDevCtx);
    CAMERA_CHECK_POINTER(pastExtDevCtx);

    if (g_sbIrInit == EI_FALSE) {
        stCtlAttr.enType = IR_CUT;
        stCtlAttr.unAttr.stIrCut.eState = IR_CLOSE;
        EXTDEV_SetAttr(dev, &stCtlAttr);
        stCtlAttr.unAttr.stIrCut.eState = IR_OPEN;
        EXTDEV_SetAttr(dev, &stCtlAttr);
        g_sbIrInit = EI_TRUE;
    }

    extprintf("--%s Init--\n", DEV_NAME);

    return s32Ret;
}

static EI_S32 __EXTDEV_InitExpFunction(EXT_DEV_FUNC_S *pstExtDevFunc)
{
    EXT_DEV_CHECK_POINTER(pstExtDevFunc);

    memset(pstExtDevFunc, 0, sizeof(EXT_DEV_FUNC_S));

    pstExtDevFunc->pfnExtDevInit     = EXTDEV_Init;
    pstExtDevFunc->pfnExtDevSetAttr   = EXTDEV_SetAttr;
    pstExtDevFunc->pfnExtDevGetAttr   = EXTDEV_GetAttr;
    pstExtDevFunc->pfnExtDevExit     = EXTDEV_Exit;

    return EI_SUCCESS;
}

/****************************************************************************
 * callback structure                                                       *
 ****************************************************************************/

static EI_S32 __EXTDEV_CtxInit(VISS_DEV dev, EXT_DEV_TYPE_E eType)
{
    EXT_DEV_STATE_S *pastExtDevCtx = EI_NULL;
    IR_S *pIr = EI_NULL;

    EXT_DEV_GET_CTX(dev, pastExtDevCtx);

    memset(pastExtDevCtx, 0, sizeof(EXT_DEV_STATE_S));

    pastExtDevCtx->pvPriv = malloc(sizeof(IR_S));
    if (EI_NULL == pastExtDevCtx->pvPriv) {
        PRT_VISS_ERR("[%d] pvPriv malloc memory failed!\n", dev);
        return -EN_ERR_NOMEM;
    }

    pastExtDevCtx->enExtDevType      = eType;
    pastExtDevCtx->pcName            = DEV_NAME;
    pIr = (IR_S *)pastExtDevCtx->pvPriv;

    memset(pIr, 0, sizeof(IR_S));
    pthread_mutex_init(&pIr->mutex, NULL);

    return EI_SUCCESS;
}

static EI_VOID __EXTDEV_CtxExit(VISS_DEV dev)
{
    EXT_DEV_STATE_S *pastExtDevCtx = EI_NULL;
    IR_S *pIr = EI_NULL;

    EXT_DEV_GET_CTX(dev, pastExtDevCtx);

    pIr = (IR_S *)pastExtDevCtx->pvPriv;
    pthread_mutex_destroy(&pIr->mutex);

    EXT_DEV_FREE(pIr);
}

static EI_S32 EXTDEV_RegisterVissCallback(VISS_DEV dev, EXT_DEV_TYPE_E eType)
{
    EI_S32 s32Ret;
    EXT_INFO_S stExtInfo;
    EXT_DEV_STATE_S *pastExtDevCtx = EI_NULL;

    s32Ret = __EXTDEV_CtxInit(dev, eType);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    EXT_DEV_GET_CTX(dev, pastExtDevCtx);

    stExtInfo.pstExtDev = pastExtDevCtx;

    s32Ret  = __EXTDEV_InitExpFunction(&stExtInfo.stExtDevFun);
    s32Ret |= VISS_ExtDevRegCallBack(dev, &stExtInfo);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s ext dev register callback function failed!\n", DEV_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 EXTDEV_UnregisterVissCallback(VISS_DEV dev)
{
    EI_S32 s32Ret;

    s32Ret = VISS_ExtDevUnRegCallBack(dev);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s ext dev unregister callback function failed!\n", DEV_NAME);
        return s32Ret;
    }

    __EXTDEV_CtxExit(dev);

    return EI_SUCCESS;
}

EXT_DEV_OBJ_S stExtDevA6208Obj = {
    .pfnRegisterVissCallback    = EXTDEV_RegisterVissCallback,
    .pfnUnRegisterVissCallback  = EXTDEV_UnregisterVissCallback,
};

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

